/**************************************************************************************************
* Title: SumGlobalMemoryManager.h
* Author: Gael Huber
* Description: Manager for global memory pools. Holds all global memory pool allocators as well as
*	the global heap allocator and manages requests from global memory.
**************************************************************************************************/
#ifndef __SUMGLOBALMEMORYMANAGER_H__
#define __SUMGLOBALMEMORYMANAGER_H__

#include "SumSingleton.h"
#include "SumMemory.h"

class GlobalMemoryManager : public Singleton<GlobalMemoryManager> {
public:
	GlobalMemoryManager(void);	// Constructor
	virtual ~GlobalMemoryManager(void);	// Destructor

	// Get singleton
	inline static GlobalMemoryManager& getSingleton(void)
	{
		assert(singleton);
		return *singleton;
	}

	// Get singleton pointer
	inline static GlobalMemoryManager* getSingletonPtr(void)
	{
		return singleton;
	}

	void startUp(void);		// Start up global allocators
	void shutDown(void);	// Shut down global allocators and free all memory

	void* alloc(size_t bytes);	// Allocate a block of memory
	void free(void* mem);		// Free a block of memory

private:
	PoolAllocator* level1;	// Level 1 pool allocator, 16 byte chunks
	PoolAllocator* level2;	// Level 2 pool allocator, 32 byte chunks
	PoolAllocator* level3;	// Level 3 pool allocator, 64 byte chunks
	HeapAllocator* level4;	// Level 4 heap allocator, all other chunk sizes

	// Start and ending addresses for the different levels of memory
	MemAddress level1Start, level1End;
	MemAddress level2Start, level2End;
	MemAddress level3Start, level3End;
	MemAddress level4Start, level4End;

};

// Overload new and delete for the benefit of the stack allocator

// Overload new for syntactic ease-of-use (permits regular initialization/allocation of objects)
inline static void* operator new (size_t size, bool global)
{
	if(global)
		return GlobalMemoryManager::getSingletonPtr()->alloc(size);
	else
		return malloc(size);
}

// Overload new[] for syntactic ease-of-use (permits regular initialization/allocation of arrays)
inline static void* operator new[] (size_t size, bool global)
{
	if(global)
		return GlobalMemoryManager::getSingletonPtr()->alloc(size);
	else
		return malloc(size);
}

// Overload delete for syntactic ease-of-use (permits regular deletion of objects)
inline static void operator delete (void* mem, bool global)
{
	if(global)
		GlobalMemoryManager::getSingletonPtr()->free(mem);
}

// Overload delete[] for syntactic ease-of-use (permits regular deletion of array objects
inline static void operator delete[] (void* mem, bool global)
{
	if(global)
		GlobalMemoryManager::getSingletonPtr()->free(mem);
}

#endif